; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=aarch64-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-ISEL
; RUN: llc -mtriple=aarch64-eabi -global-isel %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GLOBAL

define i64 @extract_v2i64(<2 x i64> %x, i32 %y) {
; CHECK-ISEL-LABEL: extract_v2i64:
; CHECK-ISEL:       // %bb.0:
; CHECK-ISEL-NEXT:    mov x0, v0.d[1]
; CHECK-ISEL-NEXT:    ret
;
; CHECK-GLOBAL-LABEL: extract_v2i64:
; CHECK-GLOBAL:       // %bb.0:
; CHECK-GLOBAL-NEXT:    mov d0, v0.d[1]
; CHECK-GLOBAL-NEXT:    fmov x0, d0
; CHECK-GLOBAL-NEXT:    ret
  %ext = extractelement <2 x i64> %x, i32 1
  ret i64 %ext
}

define i64 @extract_v1i64(<1 x i64> %x, i32 %y) {
; CHECK-ISEL-LABEL: extract_v1i64:
; CHECK-ISEL:       // %bb.0:
; CHECK-ISEL-NEXT:    ret
;
; CHECK-GLOBAL-LABEL: extract_v1i64:
; CHECK-GLOBAL:       // %bb.0:
; CHECK-GLOBAL-NEXT:    fmov x0, d0
; CHECK-GLOBAL-NEXT:    ret
  %ext = extractelement <1 x i64> %x, i32 1
  ret i64 %ext
}

define i32 @extract_v4i32(<4 x i32> %x, i32 %y) {
; CHECK-ISEL-LABEL: extract_v4i32:
; CHECK-ISEL:       // %bb.0:
; CHECK-ISEL-NEXT:    mov w0, v0.s[1]
; CHECK-ISEL-NEXT:    ret
;
; CHECK-GLOBAL-LABEL: extract_v4i32:
; CHECK-GLOBAL:       // %bb.0:
; CHECK-GLOBAL-NEXT:    mov s0, v0.s[1]
; CHECK-GLOBAL-NEXT:    fmov w0, s0
; CHECK-GLOBAL-NEXT:    ret
  %ext = extractelement <4 x i32> %x, i32 1
  ret i32 %ext
}

define i32 @extract_v2i32(<2 x i32> %x, i32 %y) {
; CHECK-ISEL-LABEL: extract_v2i32:
; CHECK-ISEL:       // %bb.0:
; CHECK-ISEL-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-ISEL-NEXT:    mov w0, v0.s[1]
; CHECK-ISEL-NEXT:    ret
;
; CHECK-GLOBAL-LABEL: extract_v2i32:
; CHECK-GLOBAL:       // %bb.0:
; CHECK-GLOBAL-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-GLOBAL-NEXT:    mov s0, v0.s[1]
; CHECK-GLOBAL-NEXT:    fmov w0, s0
; CHECK-GLOBAL-NEXT:    ret
  %ext = extractelement <2 x i32> %x, i32 1
  ret i32 %ext
}

define i16 @extract_v8i16(<8 x i16> %x, i32 %y) {
; CHECK-LABEL: extract_v8i16:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w0, v0.h[1]
; CHECK-NEXT:    ret
  %ext = extractelement <8 x i16> %x, i32 1
  ret i16 %ext
}

define i16 @extract_v4i16(<4 x i16> %x, i32 %y) {
; CHECK-LABEL: extract_v4i16:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w0, v0.h[1]
; CHECK-NEXT:    ret
  %ext = extractelement <4 x i16> %x, i32 1
  ret i16 %ext
}

define i8 @extract_v16i8(<16 x i8> %x, i32 %y) {
; CHECK-LABEL: extract_v16i8:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w0, v0.b[1]
; CHECK-NEXT:    ret
  %ext = extractelement <16 x i8> %x, i32 1
  ret i8 %ext
}

define i8 @extract_v8i8(<8 x i8> %x, i32 %y) {
; CHECK-LABEL: extract_v8i8:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w0, v0.b[1]
; CHECK-NEXT:    ret
  %ext = extractelement <8 x i8> %x, i32 1
  ret i8 %ext
}


define i64 @sv2i32i64(<2 x i32> %x) {
; CHECK-LABEL: sv2i32i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov x0, v0.s[1]
; CHECK-NEXT:    ret
  %e = extractelement <2 x i32> %x, i64 1
  %s = sext i32 %e to i64
  ret i64 %s
}

define i64 @sv4i32i64(<4 x i32> %x) {
; CHECK-LABEL: sv4i32i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov x0, v0.s[2]
; CHECK-NEXT:    ret
  %e = extractelement <4 x i32> %x, i64 2
  %s = sext i32 %e to i64
  ret i64 %s
}

define i64 @sv4i16i64(<4 x i16> %x) {
; CHECK-LABEL: sv4i16i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov x0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <4 x i16> %x, i64 2
  %s = sext i16 %e to i64
  ret i64 %s
}

define i64 @sv8i16i64(<8 x i16> %x) {
; CHECK-LABEL: sv8i16i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov x0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = sext i16 %e to i64
  ret i64 %s
}

define i64 @sv8i8i64(<8 x i8> %x) {
; CHECK-LABEL: sv8i8i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov x0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = sext i8 %e to i64
  ret i64 %s
}

define i64 @sv16i8i64(<16 x i8> %x) {
; CHECK-LABEL: sv16i8i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov x0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <16 x i8> %x, i64 2
  %s = sext i8 %e to i64
  ret i64 %s
}

define i32 @sv8i16i32(<8 x i16> %x) {
; CHECK-LABEL: sv8i16i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov w0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = sext i16 %e to i32
  ret i32 %s
}

define i32 @sv4i16i32(<4 x i16> %x) {
; CHECK-LABEL: sv4i16i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov w0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <4 x i16> %x, i64 2
  %s = sext i16 %e to i32
  ret i32 %s
}

define i32 @sv16i8i32(<16 x i8> %x) {
; CHECK-LABEL: sv16i8i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <16 x i8> %x, i64 2
  %s = sext i8 %e to i32
  ret i32 %s
}

define i32 @sv8i8i32(<8 x i8> %x) {
; CHECK-LABEL: sv8i8i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = sext i8 %e to i32
  ret i32 %s
}

define i16 @sv16i8i16(<16 x i8> %x) {
; CHECK-LABEL: sv16i8i16:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <16 x i8> %x, i64 2
  %s = sext i8 %e to i16
  ret i16 %s
}

define i16 @sv8i8i16(<8 x i8> %x) {
; CHECK-LABEL: sv8i8i16:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = sext i8 %e to i16
  ret i16 %s
}



define i64 @zv2i32i64(<2 x i32> %x) {
; CHECK-LABEL: zv2i32i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    mov w0, v0.s[1]
; CHECK-NEXT:    ret
  %e = extractelement <2 x i32> %x, i64 1
  %s = zext i32 %e to i64
  ret i64 %s
}

define i64 @zv4i32i64(<4 x i32> %x) {
; CHECK-LABEL: zv4i32i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    mov w0, v0.s[2]
; CHECK-NEXT:    ret
  %e = extractelement <4 x i32> %x, i64 2
  %s = zext i32 %e to i64
  ret i64 %s
}

define i64 @zv4i16i64(<4 x i16> %x) {
; CHECK-LABEL: zv4i16i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <4 x i16> %x, i64 2
  %s = zext i16 %e to i64
  ret i64 %s
}

define i64 @zv8i16i64(<8 x i16> %x) {
; CHECK-LABEL: zv8i16i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = zext i16 %e to i64
  ret i64 %s
}

define i64 @zv8i8i64(<8 x i8> %x) {
; CHECK-LABEL: zv8i8i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = zext i8 %e to i64
  ret i64 %s
}

define i64 @zv16i8i64(<16 x i8> %x) {
; CHECK-LABEL: zv16i8i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <16 x i8> %x, i64 2
  %s = zext i8 %e to i64
  ret i64 %s
}

define i32 @zv8i16i32(<8 x i16> %x) {
; CHECK-LABEL: zv8i16i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = zext i16 %e to i32
  ret i32 %s
}

define i32 @zv4i16i32(<4 x i16> %x) {
; CHECK-LABEL: zv4i16i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w0, v0.h[2]
; CHECK-NEXT:    ret
  %e = extractelement <4 x i16> %x, i64 2
  %s = zext i16 %e to i32
  ret i32 %s
}

define i32 @zv16i8i32(<16 x i8> %x) {
; CHECK-LABEL: zv16i8i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <16 x i8> %x, i64 2
  %s = zext i8 %e to i32
  ret i32 %s
}

define i32 @zv8i8i32(<8 x i8> %x) {
; CHECK-LABEL: zv8i8i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = zext i8 %e to i32
  ret i32 %s
}

define i16 @zv16i8i16(<16 x i8> %x) {
; CHECK-LABEL: zv16i8i16:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <16 x i8> %x, i64 2
  %s = zext i8 %e to i16
  ret i16 %s
}

define i16 @zv8i8i16(<8 x i8> %x) {
; CHECK-LABEL: zv8i8i16:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w0, v0.b[2]
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = zext i8 %e to i16
  ret i16 %s
}


define i32 @both_i16i32(<8 x i16> %x) {
; CHECK-LABEL: both_i16i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w8, v0.h[2]
; CHECK-NEXT:    smov w9, v0.h[2]
; CHECK-NEXT:    eor w0, w8, w9
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = zext i16 %e to i32
  %t = sext i16 %e to i32
  %u = xor i32 %s, %t
  ret i32 %u
}

define i32 @redundant_i16i32(<8 x i16> %x) {
; CHECK-LABEL: redundant_i16i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov w8, v0.h[2]
; CHECK-NEXT:    eor w0, w8, w8, lsl #16
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = sext i16 %e to i32
  %t = shl i32 %s, 16
  %u = xor i32 %s, %t
  ret i32 %u
}

define i32 @both_i8i32(<8 x i8> %x) {
; CHECK-LABEL: both_i8i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w8, v0.b[2]
; CHECK-NEXT:    smov w9, v0.b[2]
; CHECK-NEXT:    eor w0, w8, w9
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = zext i8 %e to i32
  %t = sext i8 %e to i32
  %u = xor i32 %s, %t
  ret i32 %u
}

define i32 @redundant_i8i32(<8 x i8> %x) {
; CHECK-LABEL: redundant_i8i32:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov w8, v0.b[2]
; CHECK-NEXT:    eor w0, w8, w8, lsl #24
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = sext i8 %e to i32
  %t = shl i32 %s, 24
  %u = xor i32 %s, %t
  ret i32 %u
}

define i64 @both_i32i64(<4 x i32> %x) {
; CHECK-LABEL: both_i32i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    mov w8, v0.s[2]
; CHECK-NEXT:    smov x9, v0.s[2]
; CHECK-NEXT:    eor x0, x8, x9
; CHECK-NEXT:    ret
  %e = extractelement <4 x i32> %x, i64 2
  %s = zext i32 %e to i64
  %t = sext i32 %e to i64
  %u = xor i64 %s, %t
  ret i64 %u
}

define i64 @redundant_i32i64(<4 x i32> %x) {
; CHECK-LABEL: redundant_i32i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov x8, v0.s[2]
; CHECK-NEXT:    eor x0, x8, x8, lsl #32
; CHECK-NEXT:    ret
  %e = extractelement <4 x i32> %x, i64 2
  %s = sext i32 %e to i64
  %t = shl i64 %s, 32
  %u = xor i64 %s, %t
  ret i64 %u
}

define i64 @both_i16i64(<8 x i16> %x) {
; CHECK-LABEL: both_i16i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    umov w8, v0.h[2]
; CHECK-NEXT:    smov x9, v0.h[2]
; CHECK-NEXT:    eor x0, x8, x9
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = zext i16 %e to i64
  %t = sext i16 %e to i64
  %u = xor i64 %s, %t
  ret i64 %u
}

define i64 @redundant_i16i64(<8 x i16> %x) {
; CHECK-LABEL: redundant_i16i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    smov x8, v0.h[2]
; CHECK-NEXT:    eor x0, x8, x8, lsl #48
; CHECK-NEXT:    ret
  %e = extractelement <8 x i16> %x, i64 2
  %s = sext i16 %e to i64
  %t = shl i64 %s, 48
  %u = xor i64 %s, %t
  ret i64 %u
}

define i64 @both_i8i64(<8 x i8> %x) {
; CHECK-LABEL: both_i8i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    umov w8, v0.b[2]
; CHECK-NEXT:    smov x9, v0.b[2]
; CHECK-NEXT:    eor x0, x8, x9
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = zext i8 %e to i64
  %t = sext i8 %e to i64
  %u = xor i64 %s, %t
  ret i64 %u
}

define i64 @redundant_i8i64(<8 x i8> %x) {
; CHECK-LABEL: redundant_i8i64:
; CHECK:       // %bb.0:
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    smov x8, v0.b[2]
; CHECK-NEXT:    eor x0, x8, x8, lsl #56
; CHECK-NEXT:    ret
  %e = extractelement <8 x i8> %x, i64 2
  %s = sext i8 %e to i64
  %t = shl i64 %s, 56
  %u = xor i64 %s, %t
  ret i64 %u
}
